package model;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import model.semantics.ConstNode;
import model.semantics.Node;

public class VariableTable<T> {

    private Map<String, Node<T>> variableAssignments;
    private T myDefaultValue;
    private Node<T> myDefaultValueNode;

    public VariableTable(T defaultValue) {
        variableAssignments = new HashMap<String, Node<T>>();
        myDefaultValue = defaultValue;
        myDefaultValueNode = new ConstNode<T>(defaultValue);
    }

    /**
     * Get the reference mapped to the variable. Return a default value if it
     * isn't in the table.
     */
    public Node<T> getAssignment(String variable) {
        Node<T> result = variableAssignments.get(variable);
        if (result == null) {
            return getDefaultValue();
        }
        return result;
    }

    /**
     * Get the default value to return if the variable does not exist in the
     * state.
     */
    public Node<T> getDefaultValue() {
        return myDefaultValueNode;
    }

    /**
     * Make a new copy of the variable table.
     */
    public VariableTable<T> clone() {
        VariableTable<T> newTable = new VariableTable<T>(myDefaultValue);
        newTable.variableAssignments = new HashMap<String, Node<T>>(
                variableAssignments);
        return newTable;
    }

    /**
     * Set a variable to map to a reference node.
     */
    public void setAssignment(String variable, Node<T> value) {
        variableAssignments.put(variable, value);
    }

    /**
     * Get the mapping of state variables to the string formats of the
     * expression. NOTE that the variable table returned is not kept in sync
     * with the current state.
     */
    public Map<String, String> getVariableTable() {
        // We make this a tree map so that the keys are in alphabetical order.
        Map<String, String> variableTable = new TreeMap<String, String>();
        for (String var : variableAssignments.keySet()) {
            String expression = variableAssignments.get(var).toString();
            variableTable.put(var, expression);
        }

        return variableTable;
    }
}
